The most flexible way to customize indentation is by writing
custom line-up functions, and associating them with specific
syntactic symbols (see c-offsets-alist).
Depending on the effect you want, it might be better to write a
c-special-indent-hook function rather than a line-up
function (see Other
Indentation).
CC Mode comes with an extensive set of predefined line-up functions, not all of which are used by the default styles. So there's a good chance the function you want already exists. See Line-Up Functions, for a list of them. If you write your own line-up function, it's probably a good idea to start working from one of these predefined functions, which can be found in the file cc-align.el. If you have written a line-up function that you think is generally useful, you're very welcome to contribute it; please contact bug-cc-mode@gnu.org.
Line-up functions are passed a single argument, the syntactic
element (see below). The return value is a
c-offsets-alist offset specification: for example,
an integer, a symbol such as +, a vector,
nil1, or even another line-up function. Full
details of these are in c-offsets-alist.
Line-up functions must not move point or change the content of the buffer (except temporarily). They are however allowed to do hidden buffer changes, i.e. setting text properties for caching purposes etc. Buffer undo recording is disabled while they run.
The syntactic element passed as the parameter to a line-up function is a cons cell of the form
(syntactic-symbol . anchor-position)
where syntactic-symbol is the symbol that the
function was called for, and anchor-position is the
anchor position (if any) for the construct that triggered the
syntactic symbol (see Syntactic
Analysis). This cons cell is how the syntactic element of a
line used to be represented in CC Mode 5.28 and earlier. Line-up
functions are still passed this cons cell, so as to preserve
compatibility with older configurations. In the future, we may
decide to convert to using the full list format—you can
prepare your setup for this by using the access functions
(c-langelem-sym, etc.) described below.
Some
syntactic symbols, e.g. arglist-cont-nonempty, have
more info in the syntactic element - typically other positions
that can be interesting besides the anchor position. That info
can't be accessed through the passed argument, which is a cons
cell. Instead, you can get this information from the variable
c-syntactic-element, which is dynamically bound to
the complete syntactic element. The variable
c-syntactic-context might also be useful - it gets
dynamically bound to the complete syntactic context. See Custom Braces.
CC Mode provides a few functions to access parts of syntactic
elements in a more abstract way. Besides making the code easier
to read, they also hide the difference between the old cons cell
form used in the line-up function argument and the new list form
used in c-syntactic-element and everywhere else. The
functions are:
Return the anchor position in langelem, or nil if there is none.
Return the column of the anchor position in langelem. Also move the point to that position unless preserve-point is non-
nil.
Return the secondary position in langelem, or
nilif there is none.Note that the return value of this function is always
nilif langelem is in the old cons cell form. Thus this function is only meaningful when used on syntactic elements taken fromc-syntactic-elementorc-syntactic-context.
Custom line-up functions can be as simple or as complex as you
like, and any syntactic symbol that appears in
c-offsets-alist can have a custom line-up function
associated with it.
[1] Returning nil is useful when
the offset specification for a syntactic element is a list
containing the line-up function (see c-offsets-alist).